LaunchTemplateをCloudFormationで便利に使う小ワザ
LaunchTemplate(起動テンプレート)、使ってますか?
同じようなEC2をぽこぽこ立ち上げたい時に使える便利なやつです。 LaunchTemplateを使用してAutoScalingグループを作成することもできます。
起動テンプレートを使用して Auto Scaling グループを作成する - Amazon EC2 Auto Scaling
バージョン管理ができることも特徴の一つです。
起動テンプレートのバージョンの管理 - Amazon Elastic Compute Cloud
しかし、LaunchTemplateはバージョン管理ができる故に、CloudFormationで取り扱う時に注意が必要です。
CloudFormationでLaunchTemplateを作る
例えば、こんなCFnテンプレートでLaunchTemplateを作ってみます。
--- AWSTemplateFormatVersion: '2010-09-09' Parameters: Ec2ImageId: Type: AWS::EC2::Image::Id SecurityGroupId: Type: AWS::EC2::SecurityGroup::Id Resources: SampleLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: sample-launchtemplate LaunchTemplateData: BlockDeviceMappings: - Ebs: VolumeSize: 8 VolumeType: gp2 DeviceName: /dev/xvda SecurityGroupIds: - !Ref SecurityGroupId EbsOptimized: false ImageId: !Ref Ec2ImageId InstanceType: t3.micro Monitoring: Enabled: true UserData: Fn::Base64: | #!/bin/bash yum -y update # setup httpd yum install -y httpd systemctl start httpd.service systemctl enable httpd.service
ここまでは何も問題無いです。
やっぱりもう少しボリュームサイズを増やしたいってことで、ボリュームサイズを変えてCFnスタックを更新してみます。どうなるでしょう?
そうすると、バージョンが2になります。 CFnで更新した場合でも、LaunchTemplate自体を更新するわけではありません。 バージョンを積み上げていく挙動をします。
CloudFormationでAutoScalingGroupを作る
次にLaunchTemplateを使用したAutoScalingGroupをCFnテンプレートで作ってみます。 LaunchTemplateはバージョンが存在するので、バージョン番号を指定する必要があります。
これがマネジメントコンソールであれば、「デフォルト」「最新」といった選択肢があります。
しかし、CFnの場合はドキュメントに記載されている通り、$Latest, $Defaultを指定することができません。マジカヨ。
Amazon EC2 Auto Scaling AutoScalingGroup LaunchTemplateSpecification - AWS CloudFormation
と、いうことはこんな風にLaunchTemplateのバージョン番号をべた書きして構築しろということでしょうか。
SampleAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: sample-ag DesiredCapacity: '1' LaunchTemplate: LaunchTemplateId: !Ref SampleLaunchTemplate Version: 1
ちょっと便利な解決方法
バージョンが上がるたびに、CFnテンプレートのバージョン番号を修正するとかだるいことはやっていられません。 実はこれを解決する方法があります。
LaunchTemplateのドキュメントを見ると、Fn::GetAtt組み込み関数を使うと最新バージョンが取得できると記載されています。 個人的にはAutoScalingのドキュメントに、ここへのリンクを張って欲しいくらいの重要な情報です。
Fn::GetAtt - AWS CloudFormation
AWS::EC2::LaunchTemplate - AWS CloudFormation
なので、こういうCFnテンプレートを作成すれば、
--- AWSTemplateFormatVersion: '2010-09-09' Parameters: Ec2ImageId: Type: AWS::EC2::Image::Id SecurityGroupId: Type: AWS::EC2::SecurityGroup::Id Resources: SampleLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: sample-launchtemplate LaunchTemplateData: BlockDeviceMappings: - Ebs: VolumeSize: 12 VolumeType: gp2 DeviceName: /dev/xvda SecurityGroupIds: - !Ref SecurityGroupId EbsOptimized: false ImageId: !Ref Ec2ImageId InstanceType: t3.micro Monitoring: Enabled: true UserData: Fn::Base64: | #!/bin/bash yum -y update # setup httpd yum install -y httpd systemctl start httpd.service systemctl enable httpd.service Outputs: LatestNumber: Value: !GetAtt SampleLaunchTemplate.LatestVersionNumber
!GetAttを使ってLaunchTemplateの最新バージョンが取得できます。
したがって、こういうCFnテンプレートを作れば、CFnで更新した最新のLaunchTemplateを参照するAutoScalingGroupを作ることができます。
--- AWSTemplateFormatVersion: '2010-09-09' Parameters: Ec2ImageId: Type: AWS::EC2::Image::Id SecurityGroupId: Type: AWS::EC2::SecurityGroup::Id SubnetIdA: Type: AWS::EC2::Subnet::Id SubnetIdC: Type: AWS::EC2::Subnet::Id Resources: SampleLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: sample-launchtemplate LaunchTemplateData: BlockDeviceMappings: - Ebs: VolumeSize: 12 VolumeType: gp2 DeviceName: /dev/xvda SecurityGroupIds: - !Ref SecurityGroupId EbsOptimized: false ImageId: !Ref Ec2ImageId InstanceType: t3.micro Monitoring: Enabled: true UserData: Fn::Base64: | #!/bin/bash yum -y update # setup httpd yum install -y httpd systemctl start httpd.service systemctl enable httpd.service SampleAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: sample-ag DesiredCapacity: '1' LaunchTemplate: LaunchTemplateId: !Ref SampleLaunchTemplate Version: !GetAtt SampleLaunchTemplate.LatestVersionNumber MaxSize: '1' MinSize: '0' Tags: - Key: Name Value: sample-ag PropagateAtLaunch: true VPCZoneIdentifier: - !Ref SubnetIdA - !Ref SubnetIdC